
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

'左侧链接列表'

import tkinter as tk
import db.sqlite3Tool as sqlite3Tool
from datetime import datetime
from enum import Enum, unique
import threading
from ssh_service import SSHService
from components.NiceButton import NiceButton

# @unique
class Color(Enum):
    BtnNormal = '#ffffff'
    BtnOnEenter = '#dbeafe'
    BtnOnActvie = '#dbeafe'

class AppLeft(object):
    def useRigth(self, right):
        self._app_right = right
        return self._app_right
    
    def create(self, master, on_label_click):
        self._link=None
        self.ssh=SSHService()
        self._master = master
        self.curLink = None
        self.curLinkId = -1
        self.on_label_click=on_label_click
        self.frame_dict={} # 保存全部列表项
        self._frame = tk.Frame(master, bg='#dbeafe', width=170, height=200)

        # 实例化DB
        self._db = sqlite3Tool.sqlite_operate('example.db')

        # date, domain, port, name, method, username, password, key_path
        # '2025-01-05', '192.168.1.11', 22, 'test', 1, 'username', 'password', ''

        # 插入数据
        # self._db.execute_sql_single('''INSERT INTO links VALUES (null, '2025-01-05', '18.183.78.213', 22, 'AWS', 2, 'ubuntu', 'Psdcd123',
        #                       'Z:\\ziliao\\aws\\aws_twq.pem',
        #                       'C:\\li\\svnwork\\well\\trunk\\05.SWC\\新空間設計\\WLLCPS-WEB-JP-i18n-aws',
        #                       'C:\\li\\svnwork\\well\\trunk\\05.SWC\\新空間設計\\WLLCPS-WEB-JP-i18n-aws\\dist.zip',
        #                       '/home/ubuntu/test',
        #                       'C:\\li\\svnwork\\well\\trunk\\05.SWC\\docker-deploy',
        #                       'test',
        #                       'test'
        #                       )''')

        # 删除数据
        # self._db.execute_sql_single("DELETE FROM links WHERE id = 'RHAT'")

        # tk.Button(self._frame, text="新增+", command=lambda: self.open_new_window(master)).pack(fill=tk.X)

        # 创建自定义按钮
        nice_button = NiceButton(self._frame, text="新增", bg_color="#4CAF50", fg_color="white", hover_color="#45a049",
                                            corner_radius=10, command=lambda: self.open_new_window(master), width=135, height=35)
        nice_button.pack(padx=5,pady=5)

        # 查询数据
        links = self._db.execute_sql_single('SELECT * FROM links')
        if len(links) > 0:
            for link in links:
                self.addFrameLabel(link)
        return self._frame
    
    def refresh(self):
        self.curLink=None
        self.curLinkId=-1
        # print("refresh")
        """清空 Frame 内的所有组件"""
        for widget in self._frame.winfo_children():
            widget.destroy()
        
        # tk.Button(self._frame, text="新增+", command=lambda: self.open_new_window(self._master)).pack(fill=tk.X)
        # 创建自定义按钮
        nice_button = NiceButton(self._frame, text="新增", bg_color="#4CAF50", fg_color="white", hover_color="#45a049",
                                            corner_radius=10, command=lambda: self.open_new_window(self._master), width=135, height=35)
        nice_button.pack(padx=5,pady=5)

        # 查询数据
        links = self._db.execute_sql_single('SELECT * FROM links')
        if len(links) > 0:
            for link in links:
                self.addFrameLabel(link)

    # 窗口居中方法
    def center_window(self, window, width, height):
        # 获取屏幕宽度和高度
        screen_width = window.winfo_screenwidth()
        screen_height = window.winfo_screenheight()
    
        # 计算窗口的x和y坐标，使窗口居中
        x = (screen_width - width) // 2
        y = (screen_height - height) // 2
    
        # 设置窗口的大小和位置
        window.geometry(f'{width}x{height}+{x}+{y}')

    def open_new_window(self, master, formType='add'):

        # 类型 新增/编辑
        self._formType=formType

        # 创建新的 Toplevel 窗口
        new_window = tk.Toplevel(master, background="#ffffff")
        new_window.title("+")
        # 设置窗口初始大小
        window_width = 1920 // 4
        window_height = 1080 // 4
        new_window.geometry(f'{window_width}x{window_height}')

        new_window.grid_columnconfigure(1, weight=1)  # 确保列配置为可扩展

        if formType=='edit': # 编辑
            # 示例：检测特定主机的SSH连接状态
            name = self._link[4] or ''        # 名称
            host = self._link[2] or ''        # 替换为目标主机的IP地址
            port = self._link[3] or ''        # 默认SSH端口
            username = self._link[6] or ''    # 替换为你的用户名
            password = self._link[7] or ''    # 替换为你的密码
            key_path = self._link[8] or ''    # 私钥目录路径
            method = self._link[5] or ''
            self._var_domain = tk.StringVar(value=host)
            self._var_port = tk.IntVar(value=port)
            self._var_name = tk.StringVar(value=name)
            self._var_method = tk.IntVar(value=method)
            self._var_username = tk.StringVar(value=username)
            self._var_password = tk.StringVar(value=password)
            self._var_key_path = tk.StringVar(value=key_path)
        else: # 新增
            self._var_domain = tk.StringVar(value="")
            self._var_port = tk.IntVar(value=22)
            self._var_name = tk.StringVar(value="")
            self._var_method = tk.IntVar(value=1)
            self._var_username = tk.StringVar(value="")
            self._var_password = tk.StringVar(value="")
            self._var_key_path = tk.StringVar(value="")

        # 在 Frame 中使用 grid 布局。 sticky="e"：右侧对齐
        # row0
        rownum = 0
        tk.Label(new_window, text="名称:", width=10, anchor='e').grid(row=rownum, column=0, padx=5, pady=5, sticky="e")
        tk.Entry(new_window, textvariable=self._var_name).grid(row=rownum, column=1, padx=5, pady=5, sticky="NSEW")
        # tk.Button(new_window, text="打开", command=lambda:self.openExplorer(self._string_var_project_path)).grid(row=rownum, column=2)

        # 在 Frame 中使用 grid 布局。 sticky="e"：右侧对齐
        # row0
        rownum = 1
        tk.Label(new_window, text="主机:").grid(row=rownum, column=0, padx=5, pady=5, sticky="e")
        tk.Entry(new_window, textvariable=self._var_domain).grid(row=rownum, column=1, padx=5, pady=5, sticky="NSEW")
        # tk.Button(new_window, text="打开", command=lambda:self.openExplorer(self._string_var_project_path)).grid(row=rownum, column=2)

        # row1
        rownum = 2
        tk.Label(new_window, text="端口:").grid(row=rownum, column=0, padx=5, pady=5, sticky="e")
        tk.Entry(new_window, textvariable=self._var_port).grid(row=rownum, column=1, padx=5, pady=5, sticky="NSEW")
        # tk.Button(new_window, text="打开", command=lambda:self.openExplorer(self._string_var_project_package_path)).grid(row=rownum, column=2)

        # row2
        rownum = 3
        tk.Label(new_window, text="用户名:").grid(row=rownum, column=0, padx=5, pady=5, sticky="e")
        tk.Entry(new_window, textvariable=self._var_username).grid(row=rownum, column=1, padx=5, pady=5, sticky="NSEW")
        # tk.Button(new_window, text="打开", command=lambda:self.openExplorer(self._string_var_docker_compose_path)).grid(row=rownum, column=2)

        # row3
        rownum = 4
        tk.Label(new_window, text="方法:").grid(row=rownum, column=0, padx=5, pady=5, sticky="e")
        # tk.Entry(new_window, textvariable=self._var_method).grid(row=rownum, column=1, padx=5, pady=5, sticky="NSEW")
        sexFrame = tk.Frame(new_window)
        sexFrame.grid(row=rownum, column=1, padx=5, pady=5, sticky="NSEW")

        # 创建单选按钮，并设置属性
        rb1 = tk.Radiobutton(
            sexFrame,
            text="密码",
            variable=self._var_method,
            value="1",  # value的值和 variable里value的值相同，表示默认选中
            command=self.on_select,
            # font=("Arial", 12),
            # state=tk.DISABLED
        )
        
        rb2 = tk.Radiobutton(
            sexFrame,
            text="秘钥",
            variable=self._var_method,
            value="2",
            command=self.on_select,
            # font=("Arial", 12),
        )
        
        rb1.pack(side=tk.LEFT, padx=10, pady=5)
        rb2.pack(side=tk.LEFT, padx=10, pady=5)

         # row5
        rownum = 5
        self._password = tk.Label(new_window, text="密码:")
        self._password.grid(row=rownum, column=0, padx=5, pady=5, sticky="e")
        self._password_entry=tk.Entry(new_window, textvariable=self._var_password)
        self._password_entry.grid(row=rownum, column=1, padx=5, pady=5, sticky="NSEW")
        # tk.Button(new_window, text="打开", command=lambda:self.openExplorer(self._string_var_docker_compose_path)).grid(row=rownum, column=2)

        self._key_path = tk.Label(new_window, text="秘钥路径:")
        # self._key_path.grid(row=rownum, column=0, padx=5, pady=5, sticky="e")
        self._key_path_entry=tk.Entry(new_window, textvariable=self._var_key_path)
        # self._key_path_entry.grid(row=rownum, column=1, padx=5, pady=5, sticky="NSEW")

        # row6
        rownum = 6
        frameBtn = tk.Frame(new_window, bg='')
        frameBtn.grid(row=rownum, column=0 , columnspan=3)
        # columnspan：跨越2列
        # tk.Button(self._frame, text="测试链接", command=check_ssh_connection).grid(row=rownum, column=1, columnspan=1, pady=10)
        btnSave = tk.Button(frameBtn, text="保存", command=lambda:self.on_save(btnSave))
        btnSave.pack(side=tk.LEFT, expand=True, fill=tk.X)
        btnCK = tk.Button(frameBtn, text="测试链接", command=lambda:self.check_ssh_connection(btnCK))
        btnCK.pack(side=tk.LEFT, expand=True, fill=tk.X)
    
        # 不能操作主窗口
        new_window.grab_set()

        self.center_window(new_window, window_width, window_height)
        self.new_window = new_window

    def open_edit_window(self):
        self.open_new_window(self._master, formType='edit')
        self.on_select()
        pass

    def close(self):
        # 关闭窗口
        # button = tk.Button(new_window, text="Close", command=new_window.destroy)
        # button.pack(pady=10)
        self.new_window.destroy()

    def create_entry_with_bottom_border(self, parent, width, height, link, on_label_click):
        # 创建一个包含 Entry 和下边框的 Frame
        frame = tk.Frame(parent, bg="#50505a", width=width, height=height)
        # frame.pack_propagate(False)  # 防止 Frame 调整其大小以适应内部控件
    
        # 创建 Entry 输入框
        # frame_entry = tk.Entry(frame, borderwidth=0, relief="flat")
        # 重要：fill=tk.BOTH, expand=True 输入框水平垂直全部填充满Frame，
        # ---- 此时输入框大小和frame大小一致，设置输入宽高失效，
        # ---- pady=(0, 2)：下划线的高度
        # frame_entry.pack(padx=0, pady=(0, 2), fill=tk.BOTH, expand=True)

        # 创建一个标签组件
        frame_label = tk.Label(frame, anchor=tk.W, text=link[4], fg="#000", bg=Color.BtnNormal.value, padx=3, pady=3)
        # 使用 pack 布局管理器放置标签
        frame_label.pack(side=tk.RIGHT, padx=0, pady=(0, 1))

        # 绑定悬停事件
        frame_label.bind("<Enter>", self.on_enter)
        frame_label.bind("<Leave>", self.on_leave)

        # 绑定鼠标左键点击事件（<Button-1> 代表左键点击）
        frame_label.bind("<Button-1>", lambda e: self.on_link_click(e, link) )
        frame_label.custom_id = link[0]
    
        frame.pack(fill=tk.X)
        
        return frame

    def on_enter(self, event):
        event.widget.config(bg=Color.BtnOnEenter.value)  # 悬停时修改背景颜色和文本
    
    def on_leave(self, event):
        link = event.widget
        if self.curLinkId == link.custom_id:
            event.widget.config(bg=Color.BtnOnActvie.value)
        else:
            event.widget.config(bg=Color.BtnNormal.value)

    def on_link_click(self, event, link):
        self._link=link
        event.widget.config(bg=Color.BtnOnActvie.value)
        self.on_label_click(event, link)
        # 取消之前选中
        if self.curLink != None and isinstance(self.curLink, tk.Label):
            self.curLink.config(bg=Color.BtnNormal.value)
        self.curLink = event.widget # 记录当前激活按钮
        self.curLinkId = link[0] # 记录当前激活按钮id

    def on_select(self):
        if (self._var_method.get() == 1):
            # print(1)
            self._key_path.grid_forget()
            self._key_path_entry.grid_forget()
            self._password.grid(row=5, column=0, padx=5, pady=5, sticky="e")
            self._password_entry.grid(row=5, column=1, padx=5, pady=5, sticky="NSEW")
        else:
            # print(2)
            self._password.grid_forget()
            self._password_entry.grid_forget()
            self._key_path.grid(row=5, column=0, padx=5, pady=5, sticky="e")
            self._key_path_entry.grid(row=5, column=1, padx=5, pady=5, sticky="NSEW")
    
    # 点击保存
    def on_save(self, btnSave):
        if self._formType=='edit': # 编辑
            self.updateLink()
        else: # 新增
            self.insertLink()

    # 新增link数据
    def insertLink(self):
        now = datetime.now()
        date = now.strftime('%Y-%m-%d %H:%M:%S')
        
        domain = self._var_domain.get()
        port = self._var_port.get()
        name = self._var_name.get()
        method = self._var_method.get()
        username = self._var_username.get()
        password = self._var_password.get()
        key_path = self._var_key_path.get()

        sqlStr = f'''INSERT INTO links VALUES (
                null, 
                '{date}', 
                '{domain}', 
                {port}, 
                '{name}',
                {method}, 
                '{username}', 
                '{password}',
                '{key_path}',
                null,
                null,
                null,
                null,
                null,
                null,
                null
            )'''

        # print(sqlStr)
        rowid = self._db.execute_sql_single(sqlStr)
        res = self._db.execute_sql_single(f'SELECT * FROM links WHERE id ={rowid}')
        if (len(res) == 1):
            link = res[0]
            self.addFrameLabel(link)
        self.close()
        self.curLink=None

    # 更新link数据
    def updateLink(self):
        domain = self._var_domain.get()
        port = self._var_port.get()
        name = self._var_name.get()
        method = self._var_method.get()
        username = self._var_username.get()
        password = self._var_password.get()
        key_path = self._var_key_path.get()

        sql = f'''
        UPDATE links SET
        domain='{domain}',
        port={port},
        name='{name}',
        method={method},
        username='{username}',
        password='{password}',
        key_path='{key_path}'
        WHERE id={self._link[0]}
        '''
        self._db.execute_sql_single(sql)

        self.refresh()
        self.close()
        self.curLink=None
        self._app_right.showHome()

    # 添加
    def addFrameLabel(self, link):
        frame_label = self.create_entry_with_bottom_border(self._frame, 100, 25, link, self.on_label_click)
        self.frame_dict[link[0]] = frame_label

    def check_ssh_connection(self, btnCK):
        domain=self._var_domain.get()
        port=self._var_port.get()
        name=self._var_name.get()
        method=self._var_method.get()
        username=self._var_username.get()
        password=self._var_password.get()
        key_path=self._var_key_path.get()

        match method:
            case 1:
                btnCK.config(state=tk.DISABLED)
                task_thread = threading.Thread(target=lambda:self.ssh.check_ssh_connection(domain, port, username, password))
                task_thread.start()
                # 检查任务是否完成
                self._frame.after(100, self.check_thread_ck, btnCK, task_thread)
            case 2:
                # ssh.connectByPrivateKey(domain, port, username, key_path)
                btnCK.config(state=tk.DISABLED)
                task_thread = threading.Thread(target=lambda:self.ssh.connectByPrivateKey(domain, port, username, key_path))
                task_thread.start()
                self._frame.after(100, self.check_thread_ck, btnCK, task_thread)
            case _: # _表示匹配到其他任何情况
                    print('无匹配模式')

    def check_thread_ck(self, btnCK, thread):
        if thread.is_alive():
            # 如果任务仍在运行，继续检查
            self._frame.after(100, self.check_thread_ck, btnCK, thread)
        else:
            # 任务完成，启用按钮并移除进度条
            btnCK.config(state=tk.NORMAL)
            # messagebox.showinfo("信息", "任务完成.")